package com.dukk.gis.tools.extensions.shadow;

import com.dukk.gis.tools.LineTool;
import org.locationtech.jts.geom.Coordinate;
import org.locationtech.jts.geom.Geometry;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;

public class LineLabelFactory {

    private List<LineInput> lineInputList;


    private Geometry lineGeo;



    public LineLabelFactory(List<LineInput> lineInputList, Geometry lineGeo){
        this.lineInputList = lineInputList;
        this.lineGeo = lineGeo;
    }

    public List<LineLabel> getLineLabel(Function<Set<Integer>, Integer> partTypeFunction){

        //投影处理
        if(this.lineInputList.get(0).isNeedShadow()){
            //投影处理 二次投影修订重叠部分后面标注不准确的问题
            doShadow();
        }

        //构造虚拟link
        virtualLineGeo();

        //投影 构造精准投影线，弥补线与线之间的交叉确实标点形状点
        doShadow();

        //二次修订精度
        //修订虚拟link保证每个投影点都在虚拟link上面
        //构造虚拟link
        virtualLineGeo();

        //投影 构造精准投影线，弥补线与线之间的交叉确实标点形状点
        doShadow();


        //标记
        CoordinateLabelTag coordinateLabelTag = new CoordinateLabelTag(this.lineInputList, this.lineGeo);
        Map<Coordinate, CoordinateLabel> coordinateLabelMap = coordinateLabelTag.doTag();

        //合线
        LineLabelPartMerge lineLabelPartMerge = new LineLabelPartMerge(coordinateLabelMap);
        LinkedList<LineLabel> lineLabelList = lineLabelPartMerge.getLineLabelList(partTypeFunction);

        return lineLabelList;
    }

    private void doShadow(){

        for(LineInput lineInput : this.lineInputList){
            Geometry lineString = lineInput.getLineString();
            if(lineInput.isNeedShadow()) {
                Geometry shadowLineString = LineTool.getExtractLine(this.lineGeo, lineString, 1);
                lineInput.setLineString(shadowLineString);
            }
        }
    }

    private void virtualLineGeo(){

        for(LineInput lineInput : this.lineInputList){
            Geometry lineString = lineInput.getLineString();
            //获取虚拟link
            Geometry virtualLineGeo = getVirtualLineGeo(lineString);
            this.lineGeo = virtualLineGeo;
        }
    }

    /**
     * 获取虚拟link
     * @param partGeo
     * @return
     */
    private Geometry getVirtualLineGeo(Geometry partGeo){

        VirtualLine virtualLine = new VirtualLine(this.lineGeo);
        virtualLine.resetLinkGeo(partGeo);
        return virtualLine.getLineGeo();
    }

}
